﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SCRUM.Core.BusinessObjects;
using SCRUM.Core.DAO;
using System.Collections.Specialized;
using SCRUM.Core.MembershipProviders;
using AjaxControlToolkit;

/// <summary>
/// Widget displays Projects, Releases and Sprints in file system like structure with possibility to browse underlying levels.
/// User may browse the hierarchy and display all subentities for choosen entity, return to parent entity
/// and perform create, update, delete operations on all of the entities while his role is Scrum master or Porduct owner.
/// Standard team member has only read access.
/// </summary>
public partial class WidgetProject2 : WidgetBase
{

    public override string Title 
    {
        get { return (string)GetLocalResourceObject("Title"); } 
    }

    public override bool IsEditable 
    {
        get { return true; }
    }

    /// <summary>
    /// Gets the name of the widget. It must be exactly the same as the folder that contains the widget.
    /// </summary>
    /// <value></value>
    public override string Name
    {
        get { return "Project2Widget"; }
    }

    /// <summary>
    /// Projects available in the application
    /// </summary>
    private IList<Project> projects;

    /// <summary>
    /// Releases for selected project
    /// </summary>
    private IList<Release> releases;

    /// <summary>
    /// Sprints available for selected release
    /// </summary>
    private IList<Sprint> sprints;

    /// <summary>
    /// Definition of columns for displayed entities
    /// </summary>
    private ColumnDef columns;

    /// <summary>
    /// The widget
    /// </summary>
    private Widget widget;

    /// <summary>
    /// Indicates that release is displayed
    /// </summary>
    private bool isRelease = false;

    /// <summary>
    /// Indicates that sprint is displayed
    /// </summary>
    private bool isSprint = false;

    /// <summary>
    /// Parent object for displayed releases
    /// </summary>
    private Project inProject;

    /// <summary>
    /// Parent object for displayed sprints
    /// </summary>
    private Release inRelease;

    /// <summary>
    /// Widget settings
    /// </summary>
    private StringDictionary settings;

    /// <summary>
    /// This method works as a substitute for Page_Load. You should use this method for
    /// data binding etc. instead of Page_Load.
    /// </summary>
    public override void LoadWidget()
    {
            //load settings for widget/user
            settings = GetSettings();
            Up.Visible = false;
            releases = null;
            sprints = null;

            //get all projects, used in combobox/main table (AllData)
            projects = DAOProject.GetAllProjects();

            //there is a user setting for project columns
            if (settings.ContainsKey("projectColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.project, settings["projectColumnDef"]);
            }
            else
            {
                //or use default
                columns = new ColumnDef(ColumnDef.project);
            }

            //set default visibility
            ProjectsLbl.Visible = true;
            ReleaseLbl.Visible = false;
            SprintLbl.Visible = false;
            ReleasesCB.Visible = false;
            ReleasesCB.SelectedIndex = -1;
            ProjectsCB.Visible = false;

            //load releases if needed
            loadReleasesAccordingToUserSettings();

            //load sprints if needed
            loadSprintsAccordingToUserSettings();

            generateColumnDef();
            //according to column definition create columns in AllData grid
            generateColumns();
            //choose datasource for AllData grid
            if (sprints != null) {
                AllData.DataSource = sprints;
              }
            else if (releases != null)
            {
                createGoColumn("GoSprint");
                AllData.DataSource = releases;
            }
            else {
                AllData.DataSource = projects;
                createGoColumn("GoRelease");
            }
            try
            {
                AllData.DataBind();
            }
            catch
            {
                //throw new Exception("Column def does not fit!");
            }
    }

    /// <summary>
    /// Loads sprints if selectedReleasesId is in settings, means user selected some release
    /// and all its sprints should be displayed
    /// </summary>
    private void loadSprintsAccordingToUserSettings()
    {
        //user selected release - load all sprints for selected release
        if (settings.ContainsKey("selectedReleaseId"))
        {
            int releaseId = System.Convert.ToInt32(settings["selectedReleaseId"]);
            inRelease = DAORelease.GetReleaseById(releaseId);

            ProjectsLbl.Visible = false;
            ReleaseLbl.Visible = false;
            SprintLbl.Visible = true;
            //try{
            sprints = DAOSprint.GetAllSprintsForRelease(releaseId);
            ReleasesCB.AutoPostBack = false;

            ReleasesCB.DataSource = releases;
            ReleasesCB.SelectedIndex = -1;
            ReleasesCB.DataBind();
            if (releases.Contains(inRelease))
            {
                ReleasesCB.SelectedValue = inRelease.ID.ToString();
            }
            ReleasesCB.Visible = true;
            ReleasesCB.AutoPostBack = true;
           //} catch (ArgumetOutOfRangeException e)
           //     {
           //         DAOWidgetSettings.DeleteSetting(widget, user, "SelectedReleaseId");
           //         DAOWidgetSettings.DeleteSetting(widget, user, "SelectedProjectId");
           //         LoadWidget();
           //     }
            Up.Visible = true;
            //mark that sprints are visible
            isSprint = true;
            if (settings.ContainsKey("sprintColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.sprint, settings["sprintColumnDef"]);
            }
            else
            {
                columns = new ColumnDef(ColumnDef.sprint);
            }
        }
    }

    /// <summary>
    /// Loads releases if selectedProjectId is in settings, means user selected some project
    /// and all its releases should be displayed
    /// </summary>
    private void loadReleasesAccordingToUserSettings()
    {
        //there is a setting that project was selected - means to load all releases for this project
        if (settings.ContainsKey("SelectedProjectId"))
        {
            int projectId = System.Convert.ToInt32(settings["SelectedProjectId"]);
            inProject = DAOProject.GetProjectById(projectId);
            ProjectsLbl.Visible = false;
            ReleaseLbl.Visible = true;
            SprintLbl.Visible = false;
            releases = DAORelease.GetAllReleasesForProject(projectId);
            Project[] prs = projects.ToArray<Project>();
            ProjectsCB.AutoPostBack = false;
            ProjectsCB.DataSource = prs;
            ProjectsCB.DataBind();
            ProjectsCB.SelectedValue = inProject.ID.ToString();
            ProjectsCB.Visible = true;
            ProjectsCB.AutoPostBack = true;
            Up.Visible = true;
            //mark that releases are visible
            isRelease = true;
            //there is a setting for column definition 
            if (settings.ContainsKey("releaseColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.release, settings["releaseColumnDef"]);
            }
            else
            {
                //show default setting
                columns = new ColumnDef(ColumnDef.release);
            }
        }
    }

    /// <summary>
    /// Creates columns based on column definition and adds them to AddData grid
    /// </summary>
    private void generateColumns()
    {
        AllData.Columns.Clear();
        foreach (String key in columns.Columns.Keys.ToArray<String>())
        {
            ButtonField column = new ButtonField();
            column.CommandName = "NameClicked";
            column.Visible = columns.Columns[key];
            column.HeaderText = (string) GetLocalResourceObject(key);
            column.DataTextField = key;
            AllData.Columns.Add(column);
        }
    }

    /// <summary>
    /// Creates column with specific command name
    /// </summary>
    /// <param name="commandName">Name of command</param>
    private void createGoColumn(string commandName)
    {
        ButtonField column1 = new ButtonField();
        column1.CommandName = commandName;
        column1.Visible = true;
        column1.HeaderText = (string)GetLocalResourceObject("GO");
        column1.Text = (string)GetLocalResourceObject("GO!");
        AllData.Columns.Add(column1);
    }

    /// <summary>
    /// Creates column definition for AddData grid and shows them to DivEdit
    /// </summary>
    private void generateColumnDef() 
    {
        List<OrderedColumn> finalList = new List<OrderedColumn>();
        if (HttpContext.Current.Session["SuperWidgetCD" + this.ID] == null)
        {
            List<OrderedColumn> enabledList = new List<OrderedColumn>();
            List<OrderedColumn> disabledList = new List<OrderedColumn>();
            foreach (String key in columns.Columns.Keys)
            {
                if (columns.Columns[key])
                {
                    enabledList.Add(new OrderedColumn(key.ToString()));
                }
                else
                {
                    disabledList.Add(new OrderedColumn(key.ToString()));
                }
            }

            finalList.AddRange(enabledList);
            finalList.Add(new OrderedColumn("-- ^Enabled, V Disabled --"));
            finalList.AddRange(disabledList);
        }
        else {
            try
            {
                finalList = (List<OrderedColumn>)HttpContext.Current.Session["SuperWidgetCD" + this.ID];
            }
            catch (InvalidCastException e) 
            {
                HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
                LoadWidget();
            }
        }

        ReorderColumns.DataSource = finalList;
        ReorderColumns.DataBind();
    }
   
    /// <summary>
    /// Method to catch all commands on the AllData grid.
    /// </summary>
    /// <param name="sender">sender</param>
    /// <param name="e">command arguments - name, selected row,...</param>
    public void handleRowCommand(Object sender, GridViewCommandEventArgs e)
    {
        // If multiple ButtonField column fields are used, use the
        // CommandName property to determine which button was clicked.
        //command to highlight row and show details of selected entity
        if (e.CommandName == "NameClicked")
        {
            hideAllDetails();
            //returns selected row
            int row = System.Convert.ToInt32( e.CommandArgument);
            if (row != -1)
            {
                if (isSprint)
                {
                    //show sprint detail
                    SprintDataDetails.AvailableSuperiorItems = releases;
                    SprintDataDetails.SuperiorItemID = inRelease.ID;
                    SprintDataDetails.DisplayItem(sprints.ElementAt(row));
                }
                else if (isRelease)
                {
                    //show release detail
                    ReleaseDataDetails.AvailableSuperiorItems = projects;
                    ReleaseDataDetails.SuperiorItemID = inProject.ID;
                    ReleaseDataDetails.DisplayItem(releases.ElementAt(row));
                }
                else
                {
                    //show project detail
                    ProjectDataDetails.DisplayItem(projects.ElementAt(row));
                }
                AllData.SelectedIndex = row;
                OkDiv.Visible = true;
                EditBtn.Visible = true;
                OkBtn.Visible = false;
                DeleteBtn.Visible = true;
            }
        }
            //command to show all releases for selected project 
        else if (e.CommandName == "GoRelease")
        {
            AllData.SelectedIndex = System.Convert.ToInt32(e.CommandArgument);
            
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedProjectId", projects[System.Convert.ToInt32(e.CommandArgument)].ID.ToString());
            hideAllDetails();
            HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
            LoadWidget();
            
        }
            //command to show all spronts for selected release
        else if (e.CommandName == "GoSprint")
        {
            AllData.SelectedIndex = System.Convert.ToInt32(e.CommandArgument);
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedReleaseId", releases[System.Convert.ToInt32(e.CommandArgument)].ID.ToString());
            hideAllDetails();
            HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
            LoadWidget();
        }

    }

    /// <summary>
    /// Shows the edit.
    /// </summary>
    public override void ShowEdit()
    {
        DivEdit.Visible = true;
    }

    /// <summary>
    /// Hides the edit.
    /// </summary>
    public override void HideEdit()
    {
        DivEdit.Visible = false;
    }

    /// <summary>
    /// Saves settings from DivEdit and hides edit.
    /// </summary>
    /// <param name="sender">sender</param>
    /// <param name="e">arguments</param>
    protected void LinkButtonSave_Click(object sender, EventArgs e)
    {
        //save config
        saveColumnDefSetting();
        hideAllDetails();
        LoadWidget();
    }

    /// <summary>
    /// Creates new settings for column definition and saves it
    /// </summary>
    private void saveColumnDefSetting()
    {
        string type = "";
        if (isSprint)
        {
            type = "sprintColumnDef";
        }
        else if (isRelease)
        {
            type = "releaseColumnDef";
        }
        else
        {
            type = "projectColumnDef";
        }
        string settings = "";
        List<OrderedColumn> cols = (List<OrderedColumn>)HttpContext.Current.Session["SuperWidgetCD" + this.ID];
        if (cols != null)
        {
            bool visible = true;
            bool line;
            foreach (OrderedColumn col in cols)
            {
                line = false;
                if (col.Data.StartsWith("--")) 
                {
                    visible = false;
                    line = true;
                }
                if (!line)
                {
                    settings = settings + col.Data + ":" + visible.ToString() + ";";
                }
            }
        }
        
        if (!settings.Equals("") && !type.Equals(""))
        {
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, type, settings);
        }

    }

    /// <summary>
    /// Reordering of column definition
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ReorderColumns_ItemReorder(object sender, 
          AjaxControlToolkit.ReorderListItemReorderEventArgs e)
            {
                //Item Reordered, so save the current order to the Session scope
                HttpContext.Current.Session["SuperWidgetCD" + this.ID] = ReorderColumns.DataSource;

            }

    /// <summary>
    /// Shows one level up entities in hierarchy: project, release, sprint.
    /// Stores this user setting for this widget.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void Up_Click(object sender, EventArgs e)
    {
        widget = DAOWidget.GetWidgetByID(this.ID);
        if (isSprint)
        {
            DAOWidgetSettings.DeleteSetting(widget, "SelectedReleaseId");
        } 
        else if (isRelease)
        {
            DAOWidgetSettings.DeleteSetting(widget, "SelectedReleaseId");
            DAOWidgetSettings.DeleteSetting(widget, "SelectedProjectId");
        }
        hideAllDetails();
        HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
        LoadWidget();
    }

    /// <summary>
    /// Change data in Alldata grid according to selection in combobox, for projects
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ProjectsCB_SelectedIndexChanged(object sender, EventArgs e)
    {            
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.DeleteSetting(widget, "SelectedReleaseId");
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedProjectId", 
                 ProjectsCB.SelectedValue.ToString());
            HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
            hideAllDetails();    
        LoadWidget();
            
    }

    /// <summary>
    /// Change data in Alldata grid according to selection in combobox, for releases
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ReleasesCB_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (ReleasesCB.Visible)
        {
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedReleaseId",
                     ReleasesCB.SelectedValue.ToString());
            HttpContext.Current.Session["SuperWidgetCD" + this.ID] = null;
            hideAllDetails();
            LoadWidget();
        }
    }

    /// <summary>
    /// Hides all detail divs
    /// </summary>
    private void hideAllDetails()
    {
        ProjectDataDetails.Visible = false;
        ReleaseDataDetails.Visible = false;
        SprintDataDetails.Visible = false;
        OkDiv.Visible = false;
        AllData.SelectedIndex = -1;
    }

    /// <summary>
    /// Creates new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void CreateBtn_Click(object sender, EventArgs e)
    {
        if (isSprint)
        {
            SprintDataDetails.AvailableSuperiorItems = releases;
            SprintDataDetails.SuperiorItemID = inRelease.ID;
            SprintDataDetails.SelectedItem = null;
        }
        else if (isRelease)
        {
            ReleaseDataDetails.AvailableSuperiorItems = projects;
            ReleaseDataDetails.SuperiorItemID = inProject.ID;
            ReleaseDataDetails.SelectedItem = null;
        }
        else
        {
            ProjectDataDetails.SelectedItem = null;
        }
        OkDiv.Visible = true;
        EditBtn.Visible = false;
        OkBtn.Visible = true;
        DeleteBtn.Visible = false;
    }

    /// <summary>
    /// Updates selected entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void EditBtn_Click(object sender, EventArgs e)
    {
        if (AllData.SelectedIndex != -1)
        {
            if (isSprint)
            {
                Sprint sprOld = (Sprint)sprints[AllData.SelectedIndex];
                SprintDataDetails.EditItem(sprOld.ID);
                SprintDataDetails.Visible = false;
                ReleasesCB_SelectedIndexChanged(new Object(), new EventArgs());
            }
            else if (isRelease)
            {
                Release relOld = (Release)releases[AllData.SelectedIndex];
                ReleaseDataDetails.EditItem(relOld.ID);
                ReleaseDataDetails.Visible = false;
                LoadWidget();
            }
            else
            {
                Project projOld = (Project)projects[AllData.SelectedIndex];
                ProjectDataDetails.EditItem(projOld.ID);
                ProjectDataDetails.Visible = false;
                LoadWidget();
            }
            hideAllDetails();
        }
    }

    /// <summary>
    /// Deletes selected entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void DeleteBtn_Click(object sender, EventArgs e)
    {
        if (AllData.SelectedIndex != -1)
        {
            if (isSprint)
            {
                SprintDataDetails.DeleteItem(sprints[AllData.SelectedIndex]);
            }
            else if (isRelease)
            {
                ReleaseDataDetails.DeleteItem(releases[AllData.SelectedIndex]);
            }
            else
            {
                ProjectDataDetails.DeleteItem(projects[AllData.SelectedIndex]);
            }
            hideAllDetails();
            LoadWidget();
        }
    }
    
    /// <summary>
    /// Confirmed createion of new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void OkBtn_Click(object sender, EventArgs e)
    {
        if (isSprint)
        {
            Sprint spr = SprintDataDetails.CreateItem();
            SprintDataDetails.Visible = true;
            ReleasesCB_SelectedIndexChanged(new Object(), new EventArgs());
        }
        else if (isRelease)
        {
            Release rel = ReleaseDataDetails.CreateItem();
            LoadWidget();
        }
        else
        {
            
            Project pro = ProjectDataDetails.CreateItem();
            LoadWidget();
        }
        hideAllDetails();
    }
 
    /// <summary>
    /// User action cancelled
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void CancelBtn_Click(object sender, EventArgs e)
    {
        hideAllDetails();
    }

    /// <summary>
    /// Change of page index
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void AllData_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        AllData.PageIndex = e.NewPageIndex;
        AllData.DataBind();
    }
}
